\chapter{Compilation policies}
\label{chap-policy}

\section{Purpose}

\commonlisp{} includes an \texttt{optimize} declaration, which can
be used to inform a compiler of what qualities the programmer would
prefer the compiler focus on in a particular lexical region. For
example, \texttt{speed} can be declared a higher priority than
\texttt{space} in a small loop that would benefit from more
aggressive inlining.

Compilation policies are \sysname{}'s way of translating these
\texttt{optimize} declarations into concrete, specific directions in
the compiler. A policy is an object computed from \texttt{optimize}
declarations containing these specific directions. Each policy
consists of several assocations of \textit{policy qualities} with
\textit{values}. Every AST and instruction includes the policy in
force for itself; optimization phases in the compiler can then
interrogate these policies for specific qualities relevant to that
pass, and proceed differently depending on this information.

Implementations define methods on \texttt{compute-policy-quality} in
order to control the translation from \texttt{optimize} declarations
to policies. \sysname{} includes several policy qualities of its own,
and an implementation can define its own policy qualities if it has
other optimizations to perform.

\section{Package}

All symbols documented in this chapter have as their home package
the package named \texttt{cleavir-compilation-policy}. This package
has a single nickname which is \texttt{cleavir-policy}.

\section{Optimize declarations}

\Defun {normalize-optimize} {optimize environment}

Given the \texttt{cdr} of an \texttt{optimize} declaration specifier,
return a normalized copy, and check for the well-formedness of the
specifier. Normalization means including default values explicitly.
This function will additionally reject specifiers with unknown
optimize qualities or with invalid values for optimize qualities.

\Defun {optimize-value} {optimize quality}

Given a normalized optimization specifier, and an \texttt{optimize}
quality, returns the value of the quality in that specifier.

\section{Computing policies}

\Defgeneric {compute-policy-quality} {name optimize environment}

Given a normalized optimization specifier as returned from
\texttt{normalize-optimize}, and the name of a policy quality, this
generic function computes the value for that policy quality.

No primary methods are provided for this function. Implementations
are expected to define methods for all policy qualities defined by
\sysname{} systems that they use.

The \textit{environment} argument is used for dispatch.

\Defaroundmethod {compute-policy-quality} {name optimize environment}

The unspecialized \texttt{:around} method on \texttt{compute-policy-quality}
looks at the optimize info to see if the policy quality being computed
is explicitly specified. If it is, that value is returned; otherwise
the next method is called.

\section{Defining policy qualities}

\Defgeneric {policy-qualities} {environment}

This generic function returns information about the policy qualities
defined in \texttt{environment}.  It is a
proper list, each element of which is a three-element list. The first
element is the name of a policy quality, the second a type specifier
for the type of values allowed for the quality, and the third the
quality's default value.

\texttt{policy-qualities} uses the \texttt{append} method combination.

\Defmethod {policy-qualities} {environment}

The default method returns the information for \sysname{}'s policy
qualities.

\section{Accessing policy information}

Only one function is defined to read information from a policy:

\Defun {policy-value} {policy quality}

Returns the value of \textit{quality} within \textit{policy}.

\section{Example}

If a policy quality is unique to the implementation, it must first
be defined. If the implementation's global environments are of class \textit{sys:global-environment}, it might define

\begin{verbatim}
  (defmethod cleavir-policy:policy-qualities
      ((environment sys:global-environment))
    '((sys:gimble-toves (member :uffish :manxome nil) nil)))
\end{verbatim}

thereby adding a single policy quality named \texttt{sys:gimble-toves},
with a value that is either \texttt{nil}, \texttt{:manxome}, or
\texttt{:uffish}, and which defaults to \texttt{nil}.

\sysname{} would have to be informed how to compute this quality with
a method on \texttt{compute-policy-quality}, like so:

\begin{verbatim}
  (defmethod cleavir-policy:compute-policy-quality
      ((name (eql 'sys:gimble-toves))
       optimize
       (environment sys:global-environment))
    (cond ((= (cleavir-policy:optimize-value optimize
                                             'compilation-speed)
              2)
           :uffish)
          ((< (cleavir-policy:optimize-value optimize 'space) 3)
           :manxome)
          (t nil)))
\end{verbatim}

Then the quality should be \texttt{:uffish} if \texttt{compilation-speed}
is exactly two, or failing that, \texttt{:manxome} if \texttt{speed}
is less than three, or otherwise \texttt{nil}.

In an internal pass, the implementation could then access the policy
and do different things based on the quality value.

\begin{verbatim}
  (defmethod snicker-snack (instruction)
    (case (cleavir-policy:policy-value
           (cleavir-ir:policy instruction)
           'sys:gimble-toves)
      (:uffish ...)
      (:manxome ...)
      (nil (do-nothing))))
\end{verbatim}
